home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Development Platforms / Apple II / Essentials / Technical.Notes / Misc / TN.MISC.002 < prev    next >
Encoding:
Text File  |  1991-06-28  |  20.8 KB  |  528 lines  |  [TEXT/pdos]

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5.  
  6.  
  7. Apple II Miscellaneous
  8. #2:    Apple II Family Identification Routines 2.2
  9.  
  10. Revised by:    Jim Luther    May 1991
  11. Revised by:    Matt Deatherage & Keith Rollin    November 1988
  12. Revised by:    Pete McDonald    January 1986
  13.  
  14. This Technical Note presents a new version of the Apple II Family 
  15. Identification Routine, a sample piece of code which shows how to identify 
  16. various Apple II computers and their memory configurations.
  17.  
  18. Changes since November 1988:  Converted the identification routine from Apple 
  19. II Assembler/Editor (EDASM) source code to Apple IIgs Programmer's Workshop 
  20. (APW) Assembler source code.  Added the Apple IIe Card for the Macintosh LC 
  21. to the identification routine's lookup table and memory check routine.  Made 
  22. minor corrections to text.
  23. _____________________________________________________________________________
  24.  
  25.  
  26. Why Identification Routines?
  27.  
  28. Although we present the Apple II family identification bytes in Apple II 
  29. Miscellaneous Technical Note #7, many people would prefer a routine they can 
  30. simply plug into their own program and call.  In addition, this routine 
  31. serves as a small piece of sample code, and there is no reason for you to 
  32. reinvent the wheel.
  33.  
  34. Most of the interesting part of the routine consists of identifying the 
  35. memory configuration of the machine.  On an Apple IIe, the routine moves code 
  36. into the zero page to test for the presence of auxiliary memory.  (A IIe with 
  37. a non-extended 80-column card is a configuration still found in many schools 
  38. throughout the country.)
  39.  
  40. The actual identification is done by a table-lookup method.
  41.  
  42.  
  43. What the Routine Returns
  44.  
  45. This version (2.2) of the identification routine returns several things:
  46.  
  47. o   A machine byte, containing one of seven values:
  48.     $00 = Unknown machine
  49.     $01 = Apple ][
  50.     $02 = Apple ][+
  51.     $03 = Apple /// in emulation mode
  52.     $04 = Apple IIe
  53.     $05 = Apple IIc
  54.     $06 = Apple IIe Card for the Macintosh LC
  55.  
  56.     In addition, if the high bit of the byte is set, the machine is a IIgs or 
  57.     equivalent.  For all current Apple IIgs computers, the value returned in 
  58.     machine is $84 (high bit set to signify Apple IIgs and $04 because it 
  59.     matches the ID bytes of an enhanced Apple IIe).
  60. o   A ROMlevel byte, indicating the revision of the firmware in the machine.  
  61.     For example, there are currently five revisions of the IIc, two of the 
  62.     IIe (unenhanced and enhanced), and three versions of the IIgs ROM (there 
  63.     will always be some owners who have not yet upgraded from ROM 00 to ROM 
  64.     01).  These versions are identified starting at $01 for the earliest.  
  65.     Therefore, the current IIc will return ROMlevel = $05, the current IIgs 
  66.     will return ROMlevel = $03, etc.  The routine will also return correct 
  67.     values for future versions of the IIgs, as a convention has been 
  68.     established for future ROM versions of that machine.
  69. o   A memory byte, containing the amount of memory in the machine.  This byte 
  70.     only has four values--0 (undefined), 48, 64, and 128.  Extra memory in an 
  71.     Apple IIgs, or extra memory in an Apple IIe or IIc Memory Expansion card, 
  72.     is not included.  Programs must take special considerations to use that 
  73.     memory (if available), beyond those considerations required to use the 
  74.     normal 128K of today's IIe and IIc.
  75. o   If running on an Apple IIgs, three word-length fields are also returned.  
  76.     These are the contents of the registers as returned by the ID routine in 
  77.     the IIgs ROM, and they indicate several things about the machine.  See 
  78.     Apple II Miscellaneous Technical Note #7 for more details.
  79.  
  80. In addition to these features, most of the addressing done in the routine is 
  81. by label.  If you wish things to be stored in different places, simply 
  82. changing the labels will often do it.
  83.  
  84.  
  85. Limitations and Improvements
  86.  
  87. As sample code, you might have already guessed that this is not the most 
  88. compact, efficient way of identifying these machines.  Some improvements you 
  89. might incorporate if using these routines include:
  90.  
  91. o    If you are running under ProDOS, you can remove the section that 
  92.      determines how much memory is in the machine (starting at exit, line 
  93.      127), since the MACHID byte (at $BF98) in ProDOS already contains this 
  94.      information for you.  This change would cut the routine down to less 
  95.      than one page of memory.
  96. o    If you know the ROM is switched in when you call the routine, you can 
  97.      remove the sections which save and restore the language card state.  Be 
  98.      careful in doing so, however, because the memory-determination routines 
  99.      switch out the ROM to see if a language card exists.
  100. o    If you need to know if a IIe is a 64K machine with a non-extended 
  101.      80-column card, you may put your own identifying routines in after line 
  102.      284.  NoAux is only reached if there is an 80-column card but only 64K 
  103.      of memory.
  104.  
  105.  
  106.  
  107. How It Works
  108.  
  109. The identification routine does the following things:
  110.  
  111. o    Disables interrupts
  112. o    Saves four bytes from the language card areas so they may be restored 
  113.      later
  114. o    Identifies all machines by a table look-up procedure
  115. o    Calls 16-bit ID routine to distinguish IIgs from other machines of any 
  116.      kind, and returns values in appropriate locations if IIgs ID routine 
  117.      returns any useful information in the registers
  118. o    Identifies memory configuration:
  119. o    If Apple /// emulation, there is 48K
  120. o    If Apple ][ or ][+, tests for presence of language card and returns 64K 
  121.      if present, otherwise, returns 48K
  122. o    If Apple IIc or IIgs, returns 128K
  123. o    If Apple IIe, tries to identify auxiliary memory
  124. o    If reading auxiliary memory, it must be there
  125. o    If reading alternate zero page, auxiliary memory is present
  126. o    If none of this is conclusive:
  127. o    Exchanges a section of the zero page with a section of code that 
  128.      switches memory banks.  The code executes in the zero page and does not 
  129.      get switched out when we attempt to switch in the auxiliary RAM.
  130. o    Jumps to relocated code on page zero:
  131. o    Switches in auxiliary memory for reading and writing
  132. o    Stores a value at $800 and sees if the same value appears at $C00.  If   
  133.      so, no auxiliary memory is present (the non-extended 80-column card has 
  134.      sparse memory mapping which causes $800 and $C00 to be the same 
  135.      location).
  136. o    Changes value at $C00 and sees if the value at $800 changes as well.  If 
  137.      so, no auxiliary memory.  If not, then there is 128K available
  138. o    Switches main memory back in for reading and writing
  139. o    Puts the zero page back like we found it
  140. o    Returns memory configuration found (either 64K or 128K)
  141. o    Restores language card and ROM state from four saved bytes
  142. o    Restores interrupt status
  143. o    Returns to caller
  144.  
  145.  
  146.            keep ID2.2
  147.  
  148.            list on
  149.  
  150.            org $2000
  151.  
  152.            longa off
  153.            longi off
  154.  
  155. *********************************************
  156. *                                           *
  157. *  Apple II Family Identification Program   *
  158. *                                           *
  159. *               Version 2.2                 *
  160. *                                           *
  161. *               March, 1990                 *
  162. *                                           *
  163. *  Includes support for the Apple IIe Card  *
  164. *  for the Macintosh LC.                    *
  165. *                                           *
  166. *********************************************
  167.  
  168.  
  169. ;  First, some global equates for the routine:
  170.  
  171. PROGRAM    start
  172.  
  173. IIplain    equ $01          ;Apple II
  174. IIplus     equ $02          ;Apple II+
  175. IIIem      equ $03          ;Apple /// in emulation mode
  176. IIe        equ $04          ;Apple IIe
  177. IIc        equ $05          ;Apple IIc
  178. IIeCard    equ $06          ;Apple IIe Card for the Macintosh LC
  179.  
  180. safe       equ $0001        ;start of code relocated to zp
  181. location   equ $06          ;zero page location to use
  182.  
  183. test1      equ $AA          ;test byte #1
  184. test2      equ $55          ;lsr of test1
  185. test3      equ $88          ;test byte #3
  186. test4      equ $EE          ;test byte #4
  187.  
  188. begpage1   equ $400         ;beginning of text page 1
  189. begpage2   equ $800         ;beginning of text page 2
  190. begsprse   equ $C00         ;byte after text page 2
  191.  
  192. clr80col   equ $C000        ;disable 80-column store
  193. set80col   equ $C001        ;enable 80-column store
  194. rdmainram  equ $C002        ;read main ram
  195. rdcardram  equ $C003        ;read aux ram
  196. wrmainram  equ $C004        ;write main ram
  197. wrcardram  equ $C005        ;write aux ram
  198. rdramrd    equ $C013        ;are we reading aux ram?
  199. rdaltzp    equ $C016        ;are we reading aux zero page?
  200. rd80col    equ $C018        ;are we using 80-columns?
  201. rdtext     equ $C01A        ;read if text is displayed
  202. rdpage2    equ $C01C        ;read if page 2 is displayed
  203. txtclr     equ $C050        ;switch in graphics
  204. txtset     equ $C051        ;switch in text
  205. txtpage1   equ $C054        ;switch in page 1
  206. txtpage2   equ $C055        ;switch in page 2
  207. ramin      equ $C080        ;read LC bank 2, write protected
  208. romin      equ $C081        ;read ROM, 2 reads write enable LC
  209. lcbank1    equ $C08B        ;LC bank 1 enable
  210.  
  211. lc1        equ $E000        ;bytes to save for LC
  212. lc2        equ $D000        ;save/restore routine
  213. lc3        equ $D400
  214. lc4        equ $D800
  215.  
  216. idroutine  equ $FE1F        ;IIgs id routine
  217.  
  218. ;  Start by saving the state of the language card banks and
  219. ;  by switching in main ROM.
  220.  
  221. strt       php              ;save the processor state
  222.            sei              ;before disabling interrupts
  223.            lda lc1          ;save four bytes from
  224.            sta save         ;ROM/RAM area for later
  225.            lda lc2          ;restoring of RAM/ROM
  226.            sta save+1       ;to original condition
  227.            lda lc3
  228.            sta save+2
  229.            lda lc4
  230.            sta save+3
  231.            lda $C081        ;read ROM
  232.            lda $C081
  233.            lda #0           ;start by assuming unknown machine
  234.            sta machine
  235.            sta romlevel
  236.  
  237. IdStart    lda location     ;save zero page locations
  238.            sta save+4       ;for later restoration
  239.            lda location+1
  240.            sta save+5
  241.            lda #$FB         ;all ID bytes are in page $FB
  242.            sta location+1   ;save in zero page as high byte
  243.            ldx #0           ;init pointer to start of ID table
  244. loop       lda IDTable,x    ;get the machine we are testing for
  245.            sta machine      ;and save it
  246.            lda IDTable+1,x  ;get the ROM level we are testing for
  247.            sta romlevel     ;and save it
  248.            ora machine      ;are both zero?
  249.            beq matched      ;yes - at end of list - leave
  250.  
  251. loop2      inx              ;bump index to loc/byte pair to test
  252.            inx
  253.            lda IDTable,x    ;get the byte that should be in ROM
  254.            beq matched      ;if zero, we're at end of list
  255.            sta location     ;save in zero page
  256.  
  257.            ldy #0           ;init index for indirect addressing
  258.            lda IDTable+1,x  ;get the byte that should be in ROM
  259.            cmp (Location),y ;is it there?
  260.            beq loop2        ;yes, so keep on looping
  261.  
  262. loop3      inx              ;we didn't match. Scoot to the end of the
  263.            inx              ;line in the ID table so we can start
  264.            lda IDTable,x    ;checking for another machine
  265.            bne loop3
  266.            inx              ;point to start of next line
  267.            bne loop         ;should always be taken
  268.  
  269. matched    anop
  270.  
  271. ;  Here we check the 16-bit ID routine at idroutine ($FE1F).  If it
  272. ;  returns with carry clear, we call it again in 16-bit
  273. ;  mode to provide more information on the machine.
  274.  
  275. idIIgs     sec              ;set the carry bit
  276.            jsr idroutine    ;Apple IIgs ID Routine
  277.            bcc idIIgs2      ;it's a IIgs or equivalent
  278.            jmp IIgsOut      ;nope, go check memory
  279. idIIgs2    lda machine      ;get the value for machine
  280.            ora #$80         ;and set the high bit
  281.            sta machine      ;put it back
  282.            clc              ;get ready to switch into native mode
  283.            xce
  284.            php              ;save the processor status
  285.            rep #$30         ;sets 16-bit registers
  286.            longa on
  287.            longi on
  288.            jsr idroutine    ;call the ID routine again
  289.            sta IIgsA        ;16-bit store!
  290.            stx IIgsX        ;16-bit store!
  291.            sty IIgsY        ;16-bit store!
  292.            plp              ;restores 8-bit registers
  293.            xce              ;switches back to whatever it was before
  294.            longa off
  295.            longi off
  296.  
  297.            ldy IIgsY        ;get the ROM vers number (starts at 0)
  298.            cpy #$02         ;is it ROM 01 or 00?
  299.            bcs idIIgs3      ;if not, don't increment
  300.            iny              ;bump it up for romlevel
  301. idIIgs3    sty romlevel     ;and put it there
  302.            cpy #$01         ;is it the first ROM?
  303.            bne IIgsOut      ;no, go on with things
  304.            lda IIgsY+1      ;check the other byte too
  305.            bne IIgsOut      ;nope, it's a IIgs successor
  306.            lda #$7F         ;fix faulty ROM 00 on the IIgs
  307.            sta IIgsA
  308. IIgsOut    anop
  309.  
  310. ******************************************
  311. * This part of the code checks for the   *
  312. * memory configuration of the machine.   *
  313. * If it's a IIgs, we've already stored   *
  314. * the total memory from above.  If it's  *
  315. * a IIc or a IIe Card, we know it's      *
  316. * 128K; if it's a ][+, we know it's at   *
  317. * least 48K and maybe 64K.  We won't     *
  318. * check for less than 48K, since that's  *
  319. * a really rare circumstance.            *
  320. ******************************************
  321.  
  322. exit       lda machine      ;get the machine kind
  323.            bmi exit128      ;it's a 16-bit machine (has 128K)
  324.            cmp #IIc         ;is it a IIc?
  325.            beq exit128      ;yup, it's got 128K
  326.            cmp #IIeCard     ;is it a IIe Card?
  327.            beq exit128      ;yes, it's got 128K
  328.            cmp #IIe         ;is it a IIe?
  329.            bne contexit     ;yes, go muck with aux memory
  330.            jmp muckaux
  331. contexit   cmp #IIIem       ;is it a /// in emulation?
  332.            bne exitII       ;nope, it's a ][ or ][+
  333.            lda #48          ;/// emulation has 48K
  334.            jmp exita
  335. exit128    lda #128         ;128K
  336. exita      sta memory
  337. exit1      lda lc1          ;time to restore the LC
  338.            cmp save         ;if all 4 bytes are the same
  339.            bne exit2        ;then LC was never on so
  340.            lda lc2          ;do nothing
  341.            cmp save+1
  342.            bne exit2
  343.            lda lc3
  344.            cmp save+2
  345.            bne exit2
  346.            lda lc4
  347.            cmp save+3
  348.            beq exit6
  349. exit2      lda $C088        ;no match! so turn first LC
  350.            lda lc1          ;bank on and check
  351.            cmp save
  352.            beq exit3
  353.            lda $C080
  354.            jmp exit6
  355. exit3      lda lc2
  356.            cmp save+1       ;if all locations check
  357.            beq exit4        ;then do more more else
  358.            lda $C080        ;turn on bank 2
  359.            jmp exit6
  360. exit4      lda lc3          ;check second byte in bank 1
  361.            cmp save+2
  362.            beq exit5
  363.            lda $C080        ;select bank 2
  364.            jmp exit6
  365. exit5      lda lc4          ;check third byte in bank 1
  366.            cmp save+3
  367.            beq exit6
  368.            lda $C080        ;select bank 2
  369. exit6      plp              ;restore interrupt status
  370.            lda save+4       ;put zero page back
  371.            sta location
  372.            lda save+5       ;like we found it
  373.            sta location+1
  374.            rts              ;and go home.
  375.  
  376. exitII     lda lcbank1      ;force in language card
  377.            lda lcbank1      ;bank 1
  378.            ldx lc2          ;save the byte there
  379.            lda #test1       ;use this as a test byte
  380.            sta lc2
  381.            eor lc2          ;if the same, should return zero
  382.            bne noLC
  383.            lsr lc2          ;check twice just to be sure
  384.            lda #test2       ;this is the shifted value
  385.            eor lc2          ;here's the second check
  386.            bne noLC
  387.            stx lc2          ;put it back!
  388.            lda #64          ;there's 64K here
  389.            jmp exita
  390. noLC       lda #48          ;no restore - no LC!
  391.            jmp exita        ;and get out of here
  392.  
  393. muckaux    ldx rdtext       ;remember graphics in X
  394.            lda rdpage2      ;remember current video display
  395.            asl A            ;in the carry bit
  396.            lda #test3       ;another test character
  397.            bit rd80col      ;remember video mode in N
  398.            sta set80col     ;enable 80-column store
  399.            php              ;save N and C flags
  400.            sta txtpage2     ;set page two
  401.            sta txtset       ;set text
  402.            ldy begpage1     ;save first character
  403.            sta begpage1     ;and replace it with test character
  404.            lda begpage1     ;get it back
  405.            sty begpage1     ;and put back what was there
  406.            plp
  407.            bcs muck2        ;stay in page 2
  408.            sta txtpage1     ;restore page 1
  409. muck1      bmi muck2        ;stay in 80-columns
  410.            sta $c000        ;turn off 80-columns
  411. muck2      tay              ;save returned character
  412.            txa              ;get graphics/text setting
  413.            bmi muck3
  414.            sta txtclr       ;turn graphics back on
  415. muck3      cpy #test3       ;finally compare it
  416.            bne nocard       ;no 80-column card!
  417.            lda rdramrd      ;is aux memory being read?
  418.            bmi muck128      ;yup, there's 128K!
  419.            lda rdaltzp      ;is aux zero page used?
  420.            bmi muck128      ;yup!
  421.            ldy #done-start
  422. move       ldx start-1,y    ;swap section of zero page
  423.            lda |safe-1,y    ;code needing safe location during
  424.            stx safe-1,y     ;reading of aux mem
  425.            sta start-1,Y
  426.            dey
  427.            bne move
  428.            jmp |safe        ;jump to safe ground
  429. back       php              ;save status
  430.            ldy #done-start  ;move zero page back
  431. move2      lda start-1,y
  432.            sta |safe-1,y
  433.            dey
  434.            bne move2
  435.            pla
  436.            bcs noaux
  437. isaux      jmp muck128      ;there is 128K
  438.  
  439. *  You can put your own routine at "noaux" if you wish to
  440. *  distinguish between 64K without an 80-column card and
  441. *  64K with an 80-column card.
  442.  
  443. noaux      anop
  444. nocard     lda #64          ;only 64K
  445.            jmp exita
  446. muck128    jmp exit128      ;there's 128K
  447.  
  448. *  This is the routine run in the safe area not affected
  449. *  by bank-switching the main and aux RAM.
  450.  
  451. start      lda #test4       ;yet another test byte
  452.            sta wrcardram    ;write to aux while on main zero page
  453.            sta rdcardram    ;read aux ram as well
  454.            sta begpage2     ;check for sparse memory mapping
  455.            lda begsprse     ;if sparse, these will be the same
  456.            cmp #test4       ;value since they're 1K apart
  457.            bne auxmem       ;yup, there's 128K!
  458.            asl begsprse     ;may have been lucky so we'll
  459.            lda begpage2     ;change the value and see what happens
  460.            cmp begsprse
  461.            bne auxmem
  462.            sec              ;oops, no auxiliary memory
  463.            bcs goback
  464. auxmem     clc
  465. goback     sta wrmainram    ;write main RAM
  466.            sta rdmainram    ;read main RAM
  467.            jmp back         ;continue with program in main mem
  468. done       nop              ;end of relocated program marker
  469.  
  470.  
  471. *  The storage locations for the returned machine ID:
  472.  
  473. machine    ds  1            ;the type of Apple II
  474. romlevel   ds  1            ;which revision of the machine
  475. memory     ds  1            ;how much memory (up to 128K)
  476. IIgsA      ds  2            ;16-bit field
  477. IIgsX      ds  2            ;16-bit field
  478. IIgsY      ds  2            ;16-bit field
  479. save       ds  6            ;six bytes for saved data
  480.  
  481. IDTable    dc  I1'1,1'      ;Apple ][
  482.            dc  H'B3 38 00'
  483.  
  484.            dc  I1'2,1'      ;Apple ][+
  485.            dc  H'B3 EA 1E AD 00'
  486.  
  487.            dc  I1'3,1'      ;Apple /// (emulation)
  488.            dc  H'B3 EA 1E 8A 00'
  489.  
  490.            dc  I1'4,1'      ;Apple IIe (original)
  491.            dc  H'B3 06 C0 EA 00'
  492.  
  493. ;  Note: You must check for the Apple IIe Card BEFORE you
  494. ;  check for the enhanced Apple IIe since the first
  495. ;  two identification bytes are the same.
  496.  
  497.            dc  I1'6,1'      ;Apple IIe Card for the Macintosh LC (1st 
  498. release)
  499.            dc  H'B3 06 C0 E0 DD 02 BE 00 00'
  500.  
  501.            dc  I1'4,2'      ;Apple IIe (enhanced)
  502.            dc  H'B3 06 C0 E0 00'
  503.  
  504.            dc  I1'5,1'      ;Apple IIc (original)
  505.            dc  H'B3 06 C0 00 BF FF 00'
  506.  
  507.            dc  I1'5,2'      ;Apple IIc (3.5 ROM)
  508.            dc  H'B3 06 C0 00 BF 00 00'
  509.  
  510.            dc  I1'5,3'      ;Apple IIc (Mem. Exp)
  511.            dc  H'B3 06 C0 00 BF 03 00'
  512.  
  513.            dc  I1'5,4'      ;Apple IIc (Rev. Mem. Exp.)
  514.            dc  H'B3 06 C0 00 BF 04 00'
  515.  
  516.            dc  I1'5,5'      ;Apple IIc Plus
  517.            dc  H'B3 06 C0 00 BF 05 00'
  518.  
  519.            dc  I1'0,0'      ;end of table
  520.  
  521.            end
  522.  
  523.  
  524. Further Reference
  525. _____________________________________________________________________________
  526.   o  Apple II Miscellaneous Technical Note #7, Apple II Family Identification
  527.  
  528.